﻿using ErrorOr;
using Gnivc.CarDealership.Api.Application.Abstractions.Repositories;
using Gnivc.CarDealership.Api.Domain.Entities;
using Gnivc.CarDealership.Api.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;

namespace Gnivc.CarDealership.Api.Infrastructure.Repositories;

public class ModelRepository : IModelRepository
{
    private readonly IApplicationDbContext _context;

    public ModelRepository(IApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<ErrorOr<IEnumerable<Model>>> GetAllAsync()
    {
        return await _context.Models
            .AsNoTracking()
            .Where(m => !m.IsDeleted)
            .ToListAsync();
    }

    public async Task<ErrorOr<IEnumerable<Model>>> GetAllByBrandAsync(Guid brandId)
    {
        return await _context.Models
            .AsNoTracking()
            .Where(m => !m.IsDeleted && m.BrandId == brandId)
            .ToListAsync();
    }

    public async Task<ErrorOr<Model?>> GetByIdAsync(Guid modelId)
    {
        var model = await _context.Models
            .Where(m => m.Id == modelId && !m.IsDeleted)
            .Include(m => m.Brand)
            .SingleOrDefaultAsync();

        if (model == null)
            return Error.NotFound();

        return model;
    }

    public async Task<ErrorOr<Created>> AddAsync(Model model)
    {
        await _context.Models.AddAsync(model);
        var result = await _context.SaveChangesAsync();

        if (result < 1)
            return Error.Unexpected();

        return new Created();
    }

    public async Task<ErrorOr<Updated>> UpdateAsync(Model model)
    {
        _context.Models.Update(model);
        var result = await _context.SaveChangesAsync();

        if (result < 1)
            return Error.Unexpected();

        return new Updated();       
    }

    public async Task<ErrorOr<Deleted>> DeleteAsync(Guid modelId)
    {
        var model = await GetByIdAsync(modelId);

        if (model.IsError)
            return model.Errors;

        model.Value!.IsDeleted = true;

        var updateResult = await UpdateAsync(model.Value);

        if (updateResult.IsError)
            return updateResult.Errors;

        return new Deleted();
    }
}
